/*
 * kernel/core/window.c
 *
 * Copyright(c) 2007-2021 Jianjun Jiang <8192542@qq.com>
 * Official site: http://xboot.org
 * Mobile phone: +86-18665388956
 * QQ: 8192542
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 *
 */

#include <xboot.h>
#include <input/keyboard.h>
#include <SDL.h>
#include "sandbox.h"

struct surface_t *sandbox_fb_sdl_surface_get(void *context);
void sandbox_fb_sdl_fb_present(void *context, struct region_list_t *rl);
void sandbox_input_event_open();

static struct window_t *default_window = NULL;
SDL_mutex *mutex;

struct window_t *window_alloc(int width, int height)
{
	struct window_t *w;
	int range[2];

	mutex = SDL_CreateMutex();

	w = malloc(sizeof(struct window_t));
	if (!w)
		return NULL;

	w->context = sandbox_fb_sdl_open(NULL, width, height);
	w->s = sandbox_fb_sdl_surface_get(w->context);
	w->rl = region_list_alloc(0);
	w->event = fifo_alloc(sizeof(struct event_t) * CONFIG_EVENT_FIFO_SIZE);

	sandbox_input_event_open();
	return default_window = w;
}

void window_region_list_clear(struct window_t *w)
{
	if (w)
		region_list_clear(w->rl);
}

void window_present(struct window_t *w, void *o, void (*draw)(struct window_t *, void *))
{
	struct surface_t *s = w->s;
	struct region_t *r;
	struct matrix_t m;
	uint32_t *p, *q;
	int x1, y1, x2, y2;
	int l, x, y;
	int n, i;

	if ((n = w->rl->count) > 0)
	{
		l = s->stride >> 2;
		for (i = 0; i < n; i++)
		{
			r = &w->rl->region[i];
			x1 = r->x;
			y1 = r->y;
			x2 = r->x + r->w;
			y2 = r->y + r->h;
			q = (uint32_t *)s->pixels + y1 * l + x1;
			for (y = y1; y < y2; y++, q += l)
			{
				for (x = x1, p = q; x < x2; x++, p++)
				{
					if ((x ^ y) & (1 << 3))
						*p = 0xffabb9bd;
					else
						*p = 0xff899598;
				}
			}
		}
		if (draw)
			draw(w, o);
	}
	sandbox_fb_sdl_fb_present(w->context, w->rl);
}

void window_exit(struct window_t *w)
{
	struct event_t e;

	if (w)
	{
		e.device = NULL;
		e.type = EVENT_TYPE_SYSTEM_EXIT;
		e.timestamp = ktime_get();
		fifo_put(w->event, (unsigned char *)&e, sizeof(struct event_t));
	}
}

int window_pump_event(struct window_t *w, struct event_t *e)
{
	int status = SDL_TryLockMutex(mutex);
	int res = 0;

	if (status == 0)
	{
		res = (w && (fifo_get(w->event, (unsigned char *)e, sizeof(struct event_t)) == sizeof(struct event_t)));
		SDL_UnlockMutex(mutex);
	}

	return res;
}

void push_event(struct event_t *e)
{
	if (SDL_LockMutex(mutex) == 0)
	{
		struct window_t *w = default_window;
		fifo_put(w->event, (unsigned char *)e, sizeof(struct event_t));
		SDL_UnlockMutex(mutex);
	}
}
